From 6c88a9537ae829cd8a4b92312e115c311e6beb42 Mon Sep 17 00:00:00 2001 From: ThePrimeAgain Date: Wed, 14 Jan 2026 18:32:30 -0700 Subject: fuzzy_find: for agents stuff --- lua/99/request-context.lua | 125 ++++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 64 deletions(-) (limited to 'lua/99/request-context.lua') diff --git a/lua/99/request-context.lua b/lua/99/request-context.lua index 2d950d5..41a1944 100644 --- a/lua/99/request-context.lua +++ b/lua/99/request-context.lua @@ -22,95 +22,92 @@ RequestContext.__index = RequestContext --- @param xid number --- @return _99.RequestContext function RequestContext.from_current_buffer(_99, xid) - local buffer = vim.api.nvim_get_current_buf() - local full_path = vim.api.nvim_buf_get_name(buffer) - local file_type = vim.bo[buffer].ft + local buffer = vim.api.nvim_get_current_buf() + local full_path = vim.api.nvim_buf_get_name(buffer) + local file_type = vim.bo[buffer].ft - if file_type == "typescriptreact" then - file_type = "typescript" - end + if file_type == "typescriptreact" then + file_type = "typescript" + end - local mds = {} - for _, md in ipairs(_99.md_files) do - table.insert(mds, md) - end + local mds = {} + for _, md in ipairs(_99.md_files) do + table.insert(mds, md) + end - return setmetatable({ - _99 = _99, - md_file_names = mds, - ai_context = {}, - tmp_file = random_file(), - buffer = buffer, - full_path = full_path, - file_type = file_type, - logger = Logger:set_id(xid), - xid = xid, - model = _99.model, - marks = {}, - }, RequestContext) + return setmetatable({ + _99 = _99, + md_file_names = mds, + ai_context = {}, + tmp_file = random_file(), + buffer = buffer, + full_path = full_path, + file_type = file_type, + logger = Logger:set_id(xid), + xid = xid, + model = _99.model, + marks = {}, + }, RequestContext) end --- @param md_file_name string --- @return self function RequestContext:add_md_file_name(md_file_name) - table.insert(self.md_file_names, md_file_name) - return self + table.insert(self.md_file_names, md_file_name) + return self end function RequestContext:_read_md_files() - local cwd = vim.uv.cwd() - local dir = vim.fn.fnamemodify(self.full_path, ":h") - - while dir:find(cwd, 1, true) == 1 do - for _, md_file_name in ipairs(self.md_file_names) do - local md_path = dir .. "/" .. md_file_name - local file = io.open(md_path, "r") - if file then - local content = file:read("*a") - file:close() - self.logger:info( - "Context#adding md file to the context", - "md_path", - md_path - ) - table.insert(self.ai_context, content) - end - end + local cwd = vim.uv.cwd() + local dir = vim.fn.fnamemodify(self.full_path, ":h") - if dir == cwd then - break - end + while dir:find(cwd, 1, true) == 1 do + for _, md_file_name in ipairs(self.md_file_names) do + local md_path = dir .. "/" .. md_file_name + local file = io.open(md_path, "r") + if file then + local content = file:read("*a") + file:close() + self.logger:info( + "Context#adding md file to the context", + "md_path", + md_path + ) + table.insert(self.ai_context, content) + end + end - dir = vim.fn.fnamemodify(dir, ":h") + if dir == cwd then + break end + + dir = vim.fn.fnamemodify(dir, ":h") + end end --- @return string[] function RequestContext:content() - return self.ai_context + return self.ai_context end --- @return self function RequestContext:finalize() - self:_read_md_files() - if self.range then - table.insert(self.ai_context, self._99.prompts.get_file_location(self)) - table.insert( - self.ai_context, - self._99.prompts.get_range_text(self.range) - ) - end - table.insert( - self.ai_context, - self._99.prompts.tmp_file_location(self.tmp_file) - ) - return self + self:_read_md_files() + if self.range then + table.insert(self.ai_context, self._99.prompts.get_file_location(self)) + table.insert(self.ai_context, self._99.prompts.get_range_text(self.range)) + end + table.insert( + self.ai_context, + self._99.prompts.tmp_file_location(self.tmp_file) + ) + return self end function RequestContext:clear_marks() - for _, mark in pairs(self.marks) do - mark:delete() - end + for _, mark in pairs(self.marks) do + mark:delete() + end end return RequestContext -- cgit v1.3-3-g829e From f12763a215a88bd52ebe1052b10679d1d706aa24 Mon Sep 17 00:00:00 2001 From: ThePrimeAgain Date: Thu, 15 Jan 2026 13:07:03 -0700 Subject: working through fill in function with prompt and additional rules --- lua/99/extensions/agents/helpers.lua | 35 +++++++++++++++++++++++++++++++++++ lua/99/extensions/agents/init.lua | 22 ++++++++++------------ lua/99/extensions/cmp.lua | 30 ++++++++++++++++++++++-------- lua/99/extensions/init.lua | 10 ++++++++++ lua/99/init.lua | 27 ++++++++++++++++++++++++++- lua/99/ops/fill-in-function.lua | 10 ++++++++-- lua/99/ops/init.lua | 3 +++ lua/99/request-context.lua | 28 ++++++++++++++++++++++++++++ scratch/custom_rules/vim.md | 2 ++ scratch/refresh.lua | 26 +++++++++++++++++--------- 10 files changed, 161 insertions(+), 32 deletions(-) (limited to 'lua/99/request-context.lua') diff --git a/lua/99/extensions/agents/helpers.lua b/lua/99/extensions/agents/helpers.lua index 708e7a0..2758ee0 100644 --- a/lua/99/extensions/agents/helpers.lua +++ b/lua/99/extensions/agents/helpers.lua @@ -19,4 +19,39 @@ function M.ls(dir) return rules end +--- @param file string +--- @param count? number +--- @return string +function M.head(file, count) + count = count or 5 + local fd = vim.uv.fs_open(file, "r", 438) + if not fd then + return "" + end + + local stat = vim.uv.fs_fstat(fd) + if not stat then + vim.uv.fs_close(fd) + return "" + end + + local data = vim.uv.fs_read(fd, stat.size, 0) + vim.uv.fs_close(fd) + + if not data then + return "" + end + + local lines = {} + for line in data:gmatch("([^\n]*)\n?") do + if count == 0 then + break + end + count = count - 1 + table.insert(lines, line) + end + + return table.concat(lines, "\n") +end + return M diff --git a/lua/99/extensions/agents/init.lua b/lua/99/extensions/agents/init.lua index 873b95e..e42c54f 100644 --- a/lua/99/extensions/agents/init.lua +++ b/lua/99/extensions/agents/init.lua @@ -37,9 +37,7 @@ function M.rules_to_items(rules) table.insert(items, rule) end for _, custom_rules in ipairs(rules.custom or {}) do - for _, rule in ipairs(custom_rules) do - table.insert(items, rule) - end + table.insert(items, custom_rules) end return items end @@ -82,18 +80,18 @@ end --- @param haystack string --- @return _99.Agents.Rule[] function M.find_rules(rules, haystack) - --- @type _99.Agents.Rule[] - local out = {} + --- @type _99.Agents.Rule[] + local out = {} - for word in haystack:gmatch("@%S+") do - local rule_string = word:sub(2) - local rule = M.get_rule_by_path(rules, rule_string) - if rule then - table.insert(out, rule) - end + for word in haystack:gmatch("@%S+") do + local rule_string = word:sub(2) + local rule = M.get_rule_by_path(rules, rule_string) + if rule then + table.insert(out, rule) end + end - return out + return out end return M diff --git a/lua/99/extensions/cmp.lua b/lua/99/extensions/cmp.lua index 30e5d2c..75cfc39 100644 --- a/lua/99/extensions/cmp.lua +++ b/lua/99/extensions/cmp.lua @@ -1,15 +1,28 @@ local Agents = require("99.extensions.agents") +local Helpers = require("99.extensions.agents.helpers") local SOURCE = "99" +--- @class _99.Extensions.CmpItem +--- @field rule _99.Agents.Rule +--- @field docs string + --- @param _99 _99.State ---- @return _99.Agents.Rule[] +--- @return _99.Extensions.CmpItem[] local function rules(_99) - return Agents.rules_to_items(Agents.rules(_99)) + local agent_rules = Agents.rules_to_items(_99.rules) + local out = {} + for _, rule in ipairs(agent_rules) do + table.insert(out, { + rule = rule, + docs = Helpers.head(rule.path), + }) + end + return out end --- @class CmpSource --- @field _99 _99.State ---- @field items _99.Agents.Rule[] +--- @field items _99.Extensions.CmpItem[] local CmpSource = {} CmpSource.__index = CmpSource @@ -62,12 +75,12 @@ function CmpSource:complete(params, callback) for _, item in ipairs(self.items) do table.insert(items, { - label = item.name, - insertText = item.path, - filterText = item.name, + label = item.rule.name, + insertText = item.rule.path, + filterText = item.rule.name, kind = 17, -- file - -- documentation = "here is the documentation and everything associated with it", - -- detail = "detail: right side hint", + documentation = item.docs, + detail = item.rule.path, }) end @@ -75,6 +88,7 @@ function CmpSource:complete(params, callback) items = items, isIncomplete = false, }) + end --- TODO: Look into what this could be diff --git a/lua/99/extensions/init.lua b/lua/99/extensions/init.lua index ceb63a5..a6e2bd6 100644 --- a/lua/99/extensions/init.lua +++ b/lua/99/extensions/init.lua @@ -27,6 +27,7 @@ return { source.init(_99) end, + --- @param _99 _99.State setup_buffer = function(_99) local source = get_source(_99.completion) if not source then @@ -34,4 +35,13 @@ return { end source.init_for_buffer(_99) end, + + --- @param _99 _99.State + refresh = function(_99) + local source = get_source(_99.completion) + if not source then + return + end + source.refresh_state(_99) + end, } diff --git a/lua/99/init.lua b/lua/99/init.lua index 91c40b8..190027a 100644 --- a/lua/99/init.lua +++ b/lua/99/init.lua @@ -7,6 +7,7 @@ local get_id = require("99.id") local RequestContext = require("99.request-context") local Range = require("99.geo").Range local Extensions = require("99.extensions") +local Agents = require("99.extensions.agents") --- @alias _99.Cleanup fun(): nil @@ -38,7 +39,7 @@ end --- @class _99.Completion --- @field source "cmp" | nil --- @field custom_rules string[] | nil ---- @field cursor_rules string defaults to .cursor/rules +--- @field cursor_rules string | nil defaults to .cursor/rules --- @class _99.Options --- @field logger _99.Logger.Options? @@ -60,6 +61,7 @@ end --- @field languages string[] --- @field display_errors boolean --- @field provider_override _99.Provider? +--- @field rules _99.Agents.Rules --- @field __active_requests _99.Cleanup[] --- @field __view_log_idx number local _99_State = {} @@ -72,6 +74,20 @@ function _99_State.new() return setmetatable(props, _99_State) end +--- TODO: This is something to understand. I bet that this is going to need +--- a lot of performance tuning. I am just reading every file, and this could +--- take a decent amount of time if there are lots of rules. +--- +--- Simple perfs: +--- 1. read 4096 bytes at a tiem instead of whole file and parse out lines +--- 2. don't show the docs +--- 3. do the operation once at setup instead of every time. +--- likely not needed to do this all the time. +function _99_State:refresh_rules() + self.rules = Agents.rules(self) + Extensions.refresh(self) +end + local _active_request_id = 0 ---@param clean_up _99.Cleanup ---@return number @@ -122,6 +138,7 @@ end --- @param operation_name string --- @return _99.RequestContext local function get_context(operation_name) + _99_state:refresh_rules() local trace_id = get_id() local context = RequestContext.from_current_buffer(_99_state, trace_id) context.logger:debug("99 Request", "method", operation_name) @@ -275,6 +292,14 @@ function _99.setup(opts) _99_state.completion.cursor_rules = _99_state.completion.cursor_rules or ".cursor/rules/" + _99_state.completion = { + cursor_rules = "scratch/cursor/rules", + custom_rules = { + "scratch/custom_rules/", + }, + source = "cmp", + } + vim.api.nvim_create_autocmd("VimLeavePre", { callback = function() _99.stop_all_requests() diff --git a/lua/99/ops/fill-in-function.lua b/lua/99/ops/fill-in-function.lua index 7d25ef5..99e91c0 100644 --- a/lua/99/ops/fill-in-function.lua +++ b/lua/99/ops/fill-in-function.lua @@ -6,6 +6,7 @@ local editor = require("99.editor") local RequestStatus = require("99.ops.request_status") local Window = require("99.window") local make_clean_up = require("99.ops.clean-up") +local Agents = require("99.extensions.agents") --- @param context _99.RequestContext --- @param res string @@ -38,8 +39,9 @@ local function update_file_with_changes(context, res) end --- @param context _99.RequestContext ---- @param additional_prompt string? -local function fill_in_function(context, additional_prompt) +--- @param opts? _99.ops.Opts +local function fill_in_function(context, opts) + opts = opts or {} local logger = context.logger:set_area("fill_in_function") local ts = editor.treesitter local buffer = vim.api.nvim_get_current_buf() @@ -60,9 +62,13 @@ local function fill_in_function(context, additional_prompt) local request = Request.new(context) local full_prompt = context._99.prompts.prompts.fill_in_function() + local additional_prompt = opts.additional_prompt if additional_prompt then full_prompt = context._99.prompts.prompts.prompt(additional_prompt, full_prompt) + + local rules = Agents.find_rules(context._99.rules, additional_prompt) + context:add_agent_rules(rules) end request:add_prompt_content(full_prompt) diff --git a/lua/99/ops/init.lua b/lua/99/ops/init.lua index c807761..710e35d 100644 --- a/lua/99/ops/init.lua +++ b/lua/99/ops/init.lua @@ -1,3 +1,6 @@ +--- @class _99.ops.Opts +--- @field additional_prompt? string +--- @field additional_rules? _99.Agents.Rule[] return { fill_in_function = require("99.ops.fill-in-function"), implement_fn = require("99.ops.implement-fn"), diff --git a/lua/99/request-context.lua b/lua/99/request-context.lua index 41a1944..9a162c2 100644 --- a/lua/99/request-context.lua +++ b/lua/99/request-context.lua @@ -57,6 +57,34 @@ function RequestContext:add_md_file_name(md_file_name) return self end +--- @param rules _99.Agents.Rule[] +function RequestContext:add_agent_rules(rules) + for _, rule in ipairs(rules) do + local file = io.open(rule.path, "r") + if file then + local content = file:read("*a") + file:close() + self.logger:info( + "Context#adding agent file to the context", + "agent_path", + rule + ) + table.insert( + self.ai_context, + string.format( + [[ +<%s> +%s +]], + rule.name, + content, + rule.name + ) + ) + end + end +end + function RequestContext:_read_md_files() local cwd = vim.uv.cwd() local dir = vim.fn.fnamemodify(self.full_path, ":h") diff --git a/scratch/custom_rules/vim.md b/scratch/custom_rules/vim.md index e69de29..f3a6435 100644 --- a/scratch/custom_rules/vim.md +++ b/scratch/custom_rules/vim.md @@ -0,0 +1,2 @@ +whenever you write any lua code that is meant to be executed in vim +add 1 print statement per line of code describing the next code diff --git a/scratch/refresh.lua b/scratch/refresh.lua index a1b6c63..6963876 100644 --- a/scratch/refresh.lua +++ b/scratch/refresh.lua @@ -1,15 +1,23 @@ +--[[ local Window = require("99.window") Window.clear_active_popups() R("99") local Ext = require("99.extensions") +local Agents = require("99.extensions.agents") local _99 = require("99") -_99.setup({ - completion = { - source = "cmp", - custom_rules = { - "scratch/custom_rules" - } - } -}) -Ext.setup_buffer(_99.__get_state()) + +local function attach() + Ext.setup_buffer(_99.__get_state()) +end +attach() + +]] + +local Ext = require("99.extensions") +local _99 = require("99") + +local function attach() + Ext.setup_buffer(_99.__get_state()) +end +attach() -- cgit v1.3-3-g829e From 6859d56e1c88e858759481abfe930d8eadbbae8e Mon Sep 17 00:00:00 2001 From: ThePrimeAgain Date: Thu, 15 Jan 2026 13:12:20 -0700 Subject: fill in function and visual (over range) integrated with rules --- lua/99/ops/fill-in-function.lua | 6 ++++++ lua/99/ops/over-range.lua | 23 ++++++++++++++++++----- lua/99/request-context.lua | 1 + lua/99/request/init.lua | 1 - 4 files changed, 25 insertions(+), 6 deletions(-) (limited to 'lua/99/request-context.lua') diff --git a/lua/99/ops/fill-in-function.lua b/lua/99/ops/fill-in-function.lua index 99e91c0..454de08 100644 --- a/lua/99/ops/fill-in-function.lua +++ b/lua/99/ops/fill-in-function.lua @@ -70,6 +70,12 @@ local function fill_in_function(context, opts) local rules = Agents.find_rules(context._99.rules, additional_prompt) context:add_agent_rules(rules) end + + local additional_rules = opts.additional_rules + if additional_rules then + context:add_agent_rules(additional_rules) + end + request:add_prompt_content(full_prompt) local request_status = RequestStatus.new( diff --git a/lua/99/ops/over-range.lua b/lua/99/ops/over-range.lua index 4cbe8f6..209be9f 100644 --- a/lua/99/ops/over-range.lua +++ b/lua/99/ops/over-range.lua @@ -2,14 +2,17 @@ local Request = require("99.request") local RequestStatus = require("99.ops.request_status") local Mark = require("99.ops.marks") local geo = require("99.geo") +local make_clean_up = require("99.ops.clean-up") +local Agents = require("99.extensions.agents") + local Range = geo.Range local Point = geo.Point -local make_clean_up = require("99.ops.clean-up") --- @param context _99.RequestContext --- @param range _99.Range ---- @param prompt string? -local function over_range(context, range, prompt) +--- @param opts? _99.ops.Opts +local function over_range(context, range, opts) + opts = opts or {} local logger = context.logger:set_area("visual") local request = Request.new(context) @@ -42,8 +45,18 @@ local function over_range(context, range, prompt) end) local full_prompt = context._99.prompts.prompts.visual_selection(range) - if prompt then - full_prompt = context._99.prompts.prompts.prompt(prompt, full_prompt) + local additional_prompt = opts.additional_prompt + if additional_prompt then + full_prompt = + context._99.prompts.prompts.prompt(additional_prompt, full_prompt) + + local rules = Agents.find_rules(context._99.rules, additional_prompt) + context:add_agent_rules(rules) + end + + local additional_rules = opts.additional_rules + if additional_rules then + context:add_agent_rules(additional_rules) end request:add_prompt_content(full_prompt) diff --git a/lua/99/request-context.lua b/lua/99/request-context.lua index 9a162c2..d90476f 100644 --- a/lua/99/request-context.lua +++ b/lua/99/request-context.lua @@ -57,6 +57,7 @@ function RequestContext:add_md_file_name(md_file_name) return self end +--- TODO: Dedupe any rules that have already been added --- @param rules _99.Agents.Rule[] function RequestContext:add_agent_rules(rules) for _, rule in ipairs(rules) do diff --git a/lua/99/request/init.lua b/lua/99/request/init.lua index 85e6b66..53a3696 100644 --- a/lua/99/request/init.lua +++ b/lua/99/request/init.lua @@ -149,7 +149,6 @@ end --- @field logger _99.Logger --- @field _content string[] --- @field _proc vim.SystemObj? - local Request = {} Request.__index = Request -- cgit v1.3-3-g829e From 5041e3d44ace75e0eeab00d8582abfba72866495 Mon Sep 17 00:00:00 2001 From: ThePrimeAgain Date: Thu, 15 Jan 2026 14:25:43 -0700 Subject: debugging fill_in_function passing in rules --- README.md | 10 +++++----- lua/99/init.lua | 5 +++++ lua/99/request-context.lua | 21 +++++++++++++++------ scratch/refresh.lua | 17 +++++++++++++++++ 4 files changed, 42 insertions(+), 11 deletions(-) (limited to 'lua/99/request-context.lua') diff --git a/README.md b/README.md index b30c623..8e2a097 100644 --- a/README.md +++ b/README.md @@ -81,12 +81,12 @@ I make the assumption you are using Lazy _99.stop_all_requests() end) - --- a example using rules + action to produce a real exciting effect - --- ~/.rules/debug.md imagine that this is a behavior that adds in - --- the behavior where printf is what you want to debug and will - --- attempt to printf the functions contents for debugging + --- Example: Using rules + actions for custom behaviors + --- Create a rule file like ~/.rules/debug.md that defines custom behavior. + --- For instance, a "debug" rule could automatically add printf statements + --- throughout a function to help debug its execution flow. vim.keymap.set("n", "9fd", function() - _99.stop_all_requests() + _99.fill_in_function() end) end, }, diff --git a/lua/99/init.lua b/lua/99/init.lua index a13185f..ceb75e7 100644 --- a/lua/99/init.lua +++ b/lua/99/init.lua @@ -167,6 +167,11 @@ function _99.info() Window.display_centered_message(info) end +--- @param path string +function _99:rule_from_path(path) + return Agents.get_rule_by_path(_99_state.rules, path) +end + --- @param opts? _99.ops.Opts function _99.fill_in_function_prompt(opts) opts = opts or {} diff --git a/lua/99/request-context.lua b/lua/99/request-context.lua index d90476f..f9a807e 100644 --- a/lua/99/request-context.lua +++ b/lua/99/request-context.lua @@ -58,17 +58,24 @@ function RequestContext:add_md_file_name(md_file_name) end --- TODO: Dedupe any rules that have already been added ---- @param rules _99.Agents.Rule[] +--- @param rules (_99.Agents.Rule | string)[] function RequestContext:add_agent_rules(rules) + self.logger:debug("add_agent_rules", "rules", rules) for _, rule in ipairs(rules) do - local file = io.open(rule.path, "r") - if file then + -- Handle both string paths and rule objects + local rule_path = type(rule) == "string" and rule or rule.path + local rule_name = type(rule) == "string" and vim.fn.fnamemodify(rule, ":t:r") or rule.name + + local expanded_path = vim.fn.expand(rule_path) + local ok, file = pcall(io.open, expanded_path, "r") + self.logger:debug("add_agent_rules", "ok", ok, "path", rule_path, "expanded-path", expanded_path) + if ok and file then local content = file:read("*a") file:close() self.logger:info( "Context#adding agent file to the context", "agent_path", - rule + rule_path ) table.insert( self.ai_context, @@ -77,11 +84,13 @@ function RequestContext:add_agent_rules(rules) <%s> %s ]], - rule.name, + rule_name, content, - rule.name + rule_name ) ) + else + self.logger:debug("unable to read agent rule", "rule", rule_path) end end end diff --git a/scratch/refresh.lua b/scratch/refresh.lua index 6963876..7634a3d 100644 --- a/scratch/refresh.lua +++ b/scratch/refresh.lua @@ -21,3 +21,20 @@ local function attach() Ext.setup_buffer(_99.__get_state()) end attach() + +function fizz_buzz(count) + local result = {} + for i = 1, count do + if i % 18 == 0 then + table.insert(result, "FizzBuzz") + elseif i % 5 == 0 then + table.insert(result, "Fizz") + elseif i % 9 == 0 then + table.insert(result, "Buzz") + else + table.insert(result, i) + end + end + return result +end + -- cgit v1.3-3-g829e From 651c7df3523454568813a1b3dbb0a49f3fea9bdd Mon Sep 17 00:00:00 2001 From: ThePrimeAgain Date: Thu, 15 Jan 2026 15:03:16 -0700 Subject: behaviors still not getting injected I dont know why... i am going to figure this out... at some point --- lua/99/extensions/agents/helpers.lua | 14 ++++++++-- lua/99/init.lua | 38 +++++++++++++++++++------ lua/99/request-context.lua | 17 ++++-------- scratch/refresh.lua | 54 +++++++++++++++--------------------- 4 files changed, 70 insertions(+), 53 deletions(-) (limited to 'lua/99/request-context.lua') diff --git a/lua/99/extensions/agents/helpers.lua b/lua/99/extensions/agents/helpers.lua index 2758ee0..963c9f8 100644 --- a/lua/99/extensions/agents/helpers.lua +++ b/lua/99/extensions/agents/helpers.lua @@ -1,10 +1,20 @@ local M = {} +--- @param path string +--- @return string +local function normalize_path(path) + if path:sub(1, 1) == "/" then + return path + end + local cwd = vim.fs.joinpath(vim.uv.cwd(), path) + return cwd +end + --- @param dir string --- @return _99.Agents.Rule[] function M.ls(dir) - local cwd = vim.fs.joinpath(vim.uv.cwd(), dir) - local glob = vim.fs.joinpath(cwd, "/*.{mdc,md}") + local current_dir = normalize_path(dir) + local glob = vim.fs.joinpath(current_dir, "/*.{mdc,md}") local files = vim.fn.glob(glob, false, true) local rules = {} diff --git a/lua/99/init.lua b/lua/99/init.lua index ceb75e7..9cb4510 100644 --- a/lua/99/init.lua +++ b/lua/99/init.lua @@ -9,6 +9,24 @@ local Range = require("99.geo").Range local Extensions = require("99.extensions") local Agents = require("99.extensions.agents") +---@param path_or_rule string | _99.Agents.Rule +local function expand(path_or_rule) + if type(path_or_rule) == "string" then + return vim.fn.expand(path_or_rule) + end + return vim.fn.expand(path_or_rule.path) +end + +--- @param opts _99.ops.Opts? +--- @return _99.ops.Opts +local function process_opts(opts) + opts = opts or {} + for i, rule in ipairs(opts.additional_rules or {}) do + opts.additional_rules[i] = expand(rule) + end + return opts +end + --- @alias _99.Cleanup fun(): nil --- @class _99.StateProps @@ -38,7 +56,7 @@ end --- @class _99.Completion --- @field source "cmp" | nil ---- @field custom_rules string[] | nil +--- @field custom_rules string[] --- @field cursor_rules string | nil defaults to .cursor/rules --- @class _99.Options @@ -169,12 +187,12 @@ end --- @param path string function _99:rule_from_path(path) - return Agents.get_rule_by_path(_99_state.rules, path) + return Agents.get_rule_by_path(_99_state.rules, expand(path)) end --- @param opts? _99.ops.Opts function _99.fill_in_function_prompt(opts) - opts = opts or {} + opts = process_opts(opts) local context = get_context("fill-in-function-with-prompt") context.logger:debug("start") @@ -200,12 +218,13 @@ end --- @param opts? _99.ops.Opts function _99.fill_in_function(opts) + opts = process_opts(opts) ops.fill_in_function(get_context("fill_in_function"), opts) end --- @param opts _99.ops.Opts function _99.visual_prompt(opts) - opts = opts or {} + opts = process_opts(opts) local context = get_context("over-range-with-prompt") context.logger:debug("start") Window.capture_input({ @@ -231,6 +250,7 @@ end --- @param context _99.RequestContext? --- @param opts _99.ops.Opts? function _99.visual(context, opts) + opts = process_opts(opts) --- TODO: Talk to teej about this. --- Visual selection marks are only set in place post visual selection. --- that means for this function to work i must escape out of visual mode @@ -274,10 +294,6 @@ function _99.next_request_logs() Window.display_full_screen_message(logs[_99_state.__view_log_idx]) end -function _99.__debug_ident() - ops.debug_ident(_99_state) -end - function _99.stop_all_requests() for _, clean_up in pairs(_99_state.__active_requests) do clean_up() @@ -303,6 +319,12 @@ function _99.setup(opts) } _99_state.completion.cursor_rules = _99_state.completion.cursor_rules or ".cursor/rules/" + _99_state.completion.custom_rules = _99_state.completion.custom_rules or {} + + local crules = _99_state.completion.custom_rules + for i, rule in ipairs(crules) do + crules[i] = expand(rule) + end vim.api.nvim_create_autocmd("VimLeavePre", { callback = function() diff --git a/lua/99/request-context.lua b/lua/99/request-context.lua index f9a807e..4765772 100644 --- a/lua/99/request-context.lua +++ b/lua/99/request-context.lua @@ -60,22 +60,17 @@ end --- TODO: Dedupe any rules that have already been added --- @param rules (_99.Agents.Rule | string)[] function RequestContext:add_agent_rules(rules) - self.logger:debug("add_agent_rules", "rules", rules) for _, rule in ipairs(rules) do -- Handle both string paths and rule objects - local rule_path = type(rule) == "string" and rule or rule.path - local rule_name = type(rule) == "string" and vim.fn.fnamemodify(rule, ":t:r") or rule.name - - local expanded_path = vim.fn.expand(rule_path) - local ok, file = pcall(io.open, expanded_path, "r") - self.logger:debug("add_agent_rules", "ok", ok, "path", rule_path, "expanded-path", expanded_path) + self.logger:debug("adding custom rule to agent", "rule", rule) + local ok, file = pcall(io.open, rule.path, "r") if ok and file then local content = file:read("*a") file:close() self.logger:info( "Context#adding agent file to the context", "agent_path", - rule_path + rule.path ) table.insert( self.ai_context, @@ -84,13 +79,13 @@ function RequestContext:add_agent_rules(rules) <%s> %s ]], - rule_name, + rule.name, content, - rule_name + rule.name ) ) else - self.logger:debug("unable to read agent rule", "rule", rule_path) + self.logger:debug("unable to read agent rule", "rule", rule) end end end diff --git a/scratch/refresh.lua b/scratch/refresh.lua index 7634a3d..687ca70 100644 --- a/scratch/refresh.lua +++ b/scratch/refresh.lua @@ -1,40 +1,30 @@ ---[[ -local Window = require("99.window") -Window.clear_active_popups() R("99") - -local Ext = require("99.extensions") -local Agents = require("99.extensions.agents") local _99 = require("99") - -local function attach() - Ext.setup_buffer(_99.__get_state()) -end -attach() - -]] - +_99.setup({ + completion = { + custom_rules = { + "~/.behaviors/", + }, + source = "cmp", + }, +}) local Ext = require("99.extensions") -local _99 = require("99") +local Agents = require("99.extensions.agents") +local Helpers = require("99.extensions.agents.helpers") -local function attach() - Ext.setup_buffer(_99.__get_state()) -end -attach() +print(vim.inspect(Agents.rules(_99.__get_state()))) +print(vim.inspect(Helpers.ls("/home/theprimeagen/.behaviors"))) function fizz_buzz(count) - local result = {} - for i = 1, count do - if i % 18 == 0 then - table.insert(result, "FizzBuzz") - elseif i % 5 == 0 then - table.insert(result, "Fizz") - elseif i % 9 == 0 then - table.insert(result, "Buzz") - else - table.insert(result, i) - end + for i = 1, count do + if i % 15 == 0 then + print("FizzBuzz") + elseif i % 3 == 0 then + print("Fizz") + elseif i % 5 == 0 then + print("Buzz") + else + print(i) end - return result + end end - -- cgit v1.3-3-g829e