summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua')
-rw-r--r--lua/99/init.lua7
-rw-r--r--lua/99/prompt.lua4
-rw-r--r--lua/99/state.lua44
-rw-r--r--lua/99/state/tracking.lua21
-rw-r--r--lua/99/utils.lua17
-rw-r--r--lua/99/window/status-window.lua (renamed from lua/99/window/in-flight.lua)120
6 files changed, 155 insertions, 58 deletions
diff --git a/lua/99/init.lua b/lua/99/init.lua
index 82cf118..2310784 100644
--- a/lua/99/init.lua
+++ b/lua/99/init.lua
@@ -5,7 +5,7 @@ local Logger = require("99.logger.logger")
local Level = require("99.logger.level")
local ops = require("99.ops")
local Window = require("99.window")
-local show_in_flight_requests = require("99.window.in-flight")
+local StatusWindow = require("99.window.status-window")
local Prompt = require("99.prompt")
local State = require("99.state")
local Extensions = require("99.extensions")
@@ -49,7 +49,7 @@ end
--- @docs base
--- @field logger? _99.Logger.Options
--- @field model? string
---- @field in_flight_options? _99.InFlight.Opts
+--- @field in_flight_options? _99.StatusWindow.Opts
--- @field md_files? string[]
--- @field provider? _99.Providers.BaseProvider
--- @field display_errors? boolean
@@ -496,7 +496,8 @@ function _99.setup(opts)
Extensions.init(_99_state)
Extensions.capture_project_root()
- show_in_flight_requests(_99_state, _99_state.in_flight_options)
+ local sw = StatusWindow.new(_99_state, opts.in_flight_options)
+ sw:start()
end
--- @param md string
diff --git a/lua/99/prompt.lua b/lua/99/prompt.lua
index 429ad7b..23b2309 100644
--- a/lua/99/prompt.lua
+++ b/lua/99/prompt.lua
@@ -51,7 +51,7 @@ local filetype_map = {
--- @field xid number TODO: we should probably get rid of this. The request pattern is not quite correct
--- @field tutorial string[]
---- @class _99.Prompt
+--- @class _99.Prompt.Properties
--- @field md_file_names string[]
--- @field model string
--- @field user_prompt string
@@ -65,6 +65,8 @@ local filetype_map = {
--- @field marks table<string, _99.Mark>
--- @field logger _99.Logger
--- @field xid number
+
+--- @class _99.Prompt : _99.Prompt.Properties
--- @field clean_ups (fun(): nil)[]
--- @field _99 _99.State
---@diagnostic disable-next-line: undefined-doc-name
diff --git a/lua/99/state.lua b/lua/99/state.lua
index 2182c98..050a5c4 100644
--- a/lua/99/state.lua
+++ b/lua/99/state.lua
@@ -1,3 +1,4 @@
+local utils = require("99.utils")
local Agents = require("99.extensions.agents")
local Extensions = require("99.extensions")
@@ -25,13 +26,8 @@ end
--- @field prompts _99.Prompts
--- @field ai_stdout_rows number
--- @field display_errors boolean
---- @field in_flight_options _99.InFlight.Opts | nil
---- @field show_in_flight_requests_window _99.window.Window | nil
---- @field show_in_flight_requests_throbber _99.Throbber | nil
--- @field provider_override _99.Providers.BaseProvider?
---- @field auto_add_skills boolean
--- @field rules _99.Agents.Rules
---- @field __view_log_idx number
--- @field __request_history _99.Prompt[]
--- @field __request_by_id table<number, _99.Prompt>
--- @field __active_marks _99.Mark[]
@@ -44,41 +40,59 @@ local function create()
return {
model = "opencode/claude-sonnet-4-5",
md_files = {},
- prompts = require("99.prompt-settings"),
ai_stdout_rows = 3,
display_errors = false,
provider_override = nil,
- auto_add_skills = false,
- __view_log_idx = 1,
__request_history = {},
__request_by_id = {},
tmp_dir = nil,
}
end
+--- @param oos _99.Options | _99.State
+local function get_tmp_dir(oos)
+ local tmp_dir = oos.tmp_dir and type(oos.tmp_dir) == "string" and oos.tmp_dir
+ or oos.__tmp_dir and oos.__tmp_dir
+ or "./tmp"
+ if tmp_dir then
+ tmp_dir = vim.fn.expand(tmp_dir)
+ end
+ return tmp_dir
+end
+
+--- @param opts _99.Options
+--- @return _99.StateProps | nil
+local function read_state_from_tmp(opts)
+ local state_file = utils.named_tmp_file(get_tmp_dir(opts), "99-state")
+ local fd = vim.uv.fs_open(state_file, "r", 438)
+ if not fd then
+ return nil
+ end
+ return utils.read_file_json_safe(state_file) --[[@as _99.StateProps]]
+end
+
--- @param opts _99.Options
--- @return _99.State
function State.new(opts)
- local props = create()
+ local props = read_state_from_tmp(opts) or create()
local _99_state = setmetatable(props, State) --[[@as _99.State]]
_99_state.in_flight_options = opts.in_flight_options or { enable = true }
_99_state.provider_override = opts.provider
_99_state.completion = opts.completion or default_completion()
_99_state.completion.custom_rules = _99_state.completion.custom_rules or {}
- _99_state.auto_add_skills = opts.auto_add_skills or false
_99_state.completion.files = _99_state.completion.files or {}
+ --- TODO: Prompt overrides would be a great thing, we just have to get there
+ --- for now, i am going to have this as just a hardcoded ... thing
+ _99_state.prompts = require("99.prompt-settings")
+
return _99_state
end
--- @return string
function State:tmp_dir()
- local tmp_dir = self.__tmp_dir or "./tmp"
- if tmp_dir then
- tmp_dir = vim.fn.expand(tmp_dir)
- end
- return tmp_dir
+ return get_tmp_dir(self)
end
--- TODO: This is something to understand. I bet that this is going to need
diff --git a/lua/99/state/tracking.lua b/lua/99/state/tracking.lua
new file mode 100644
index 0000000..afcddd0
--- /dev/null
+++ b/lua/99/state/tracking.lua
@@ -0,0 +1,21 @@
+-- --- @class _99.State.Tracking.Options
+-- --- @field __request_history _99.Prompt[] | nil
+-- --- vj
+-- --- @field __request_by_id table<number, _99.Prompt> | nil
+-- --- v
+-- --- @field __active_marks _99.Mark[] | nil
+--
+-- --- @class _99.State.Tracking
+-- --- @field __request_history _99.Prompt[]
+-- --- @field __request_by_id table<number, _99.Prompt>
+-- --- @field __active_marks _99.Mark[]
+-- local Tracking = {}
+--
+-- --- @param previous_state
+-- function Tracking.new(previous_state)
+-- end
+--
+--
+-- return Tracking
+--
+return {}
diff --git a/lua/99/utils.lua b/lua/99/utils.lua
index e15e178..724b3c6 100644
--- a/lua/99/utils.lua
+++ b/lua/99/utils.lua
@@ -40,4 +40,21 @@ function M.named_tmp_file(dir, name)
return string.format("%s/99-%s", dir, name)
end
+--- @param path string
+--- @return table | nil
+function M.read_file_json_safe(path)
+ local ok, fh = pcall(io.open, path, "r")
+ if ok and fh then
+ local ok2, content = pcall(fh.read, fh, "*a")
+ pcall(fh.close, fh)
+ if not ok2 then
+ return nil
+ end
+ local ok3, obj = pcall(vim.json, content)
+ if ok3 and obj then
+ return obj
+ end
+ end
+end
+
return M
diff --git a/lua/99/window/in-flight.lua b/lua/99/window/status-window.lua
index 9605688..676042b 100644
--- a/lua/99/window/in-flight.lua
+++ b/lua/99/window/status-window.lua
@@ -2,8 +2,21 @@ local Window = require("99.window")
local Consts = require("99.consts")
local Throbber = require("99.ops.throbber")
---- @param opts _99.InFlight.Opts | nil
---- @return _99.InFlight.Opts
+--- @alias _99.StatusWindow.State "init" | "running"
+
+--- @class _99.StatusWindow.Opts
+--- this is pure a class for testing. helps controls timings
+--- @docs include
+--- @field throbber_opts _99.Throbber.Opts | nil
+--- options for the throbber in the top left
+--- @field in_flight_interval number | nil
+--- frequency in which the in-flight interval checks to see if it should be
+--- displayed / removed
+--- @field enable boolean | nil
+--- defaults to true
+
+--- @param opts _99.StatusWindow.Opts | nil
+--- @return _99.StatusWindow.Opts
local function default_opts(opts)
opts = opts or {}
opts.throbber_opts = opts.throbber_opts
@@ -18,53 +31,56 @@ local function default_opts(opts)
return opts
end
+--- @class _99.StatusWindow
+--- @field opts _99.StatusWindow.Opts
+--- @field state _99.StatusWindow.State
+--- @field win _99.window.Window | nil
+--- @field throbber _99.Throbber | nil
+--- @field _99 _99.State
+local StatusWindow = {}
+StatusWindow.__index = StatusWindow
+
--- @param _99 _99.State
-local function shut_down_in_flight_requests_window(_99)
- if _99.show_in_flight_requests_throbber then
- _99.show_in_flight_requests_throbber:stop()
+--- @param opts _99.StatusWindow.Opts | nil
+function StatusWindow.new(_99, opts)
+ return setmetatable({
+ opts = default_opts(opts),
+ state = "init",
+ _99 = _99,
+ }, StatusWindow)
+end
+
+function StatusWindow:_shutdown_status_window()
+ if self.throbber then
+ self.throbber:stop()
end
- local win = _99.show_in_flight_requests_window
+ local win = self.win
if win ~= nil then
Window.close(win)
end
- _99.show_in_flight_requests_window = nil
- _99.show_in_flight_requests_throbber = nil
+ self.win = nil
+ self.throbber = nil
end
---- @class _99.InFlight.Opts
---- this is pure a class for testing. helps controls timings
---- @docs include
---- @field throbber_opts _99.Throbber.Opts | nil
---- options for the throbber in the top left
---- @field in_flight_interval number | nil
---- frequency in which the in-flight interval checks to see if it should be
---- displayed / removed
---- @field enable boolean | nil
---- defaults to true
-
---- @param _99 _99.State
---- @param opts _99.InFlight.Opts | nil
-local function show_in_flight_requests(_99, opts)
- --- TODO: I dont like this. i dont like that i have to redo this every single
- --- time i cycle, but its not a big deal right now. either way ill address this later
- opts = default_opts(opts)
- if opts.enable == false then
+function StatusWindow:_run_loop()
+ if self.state ~= "running" then
+ self:_shutdown_status_window()
return
end
vim.defer_fn(function()
- show_in_flight_requests(_99, opts)
- end, opts.in_flight_interval)
+ self:_run_loop()
+ end, self.opts.in_flight_interval)
Window.refresh_active_windows()
- local current_win = _99.show_in_flight_requests_window
+ local current_win = self.win
if current_win ~= nil and not Window.is_active_window(current_win) then
- shut_down_in_flight_requests_window(_99)
+ self:_shutdown_status_window()
end
local active_window = Window.has_active_status_window()
local active_other_window = Window.has_active_windows()
- local active_requests = _99:active_request_count()
+ local active_requests = self._99:active_request_count()
if
active_window == false and active_other_window
or active_window and active_requests > 0
@@ -73,7 +89,7 @@ local function show_in_flight_requests(_99, opts)
return
end
- if _99.show_in_flight_requests_window == nil then
+ if current_win == nil then
local ok, win = pcall(Window.status_window)
if not ok then
--- TODO: There needs to be a way to display logs for "all active requests"
@@ -82,11 +98,11 @@ local function show_in_flight_requests(_99, opts)
end
local throb = Throbber.new(function(throb)
- local count = _99:active_request_count()
+ local count = self._99:active_request_count()
local win_valid = Window.valid(win)
if count == 0 or not win_valid then
- return shut_down_in_flight_requests_window(_99)
+ return self:_shutdown_status_window()
end
--- @type string[]
@@ -94,7 +110,7 @@ local function show_in_flight_requests(_99, opts)
throb .. " requests(" .. tostring(count) .. ") " .. throb,
}
- for _, c in pairs(_99.__request_by_id) do
+ for _, c in pairs(self._99.__request_by_id) do
if c.state == "requesting" then
table.insert(lines, c.operation)
end
@@ -102,13 +118,39 @@ local function show_in_flight_requests(_99, opts)
Window.resize(win, #lines[1], #lines)
vim.api.nvim_buf_set_lines(win.buf_id, 0, -1, false, lines)
- end, opts.throbber_opts)
+ end, self.opts.throbber_opts)
- _99.show_in_flight_requests_window = win
- _99.show_in_flight_requests_throbber = throb
+ self.win = win
+ self.throbber = throb
throb:start()
end
end
-return show_in_flight_requests
+function StatusWindow:start()
+ if not self.opts.enable then
+ return
+ end
+
+ assert(
+ self.state == "init",
+ "you cannot start an inflight request if we are not in init state: "
+ .. self.state
+ )
+
+ self.state = "running"
+ self:_run_loop()
+end
+
+function StatusWindow:stop()
+ if not self.opts.enable then
+ return
+ end
+ assert(
+ self.state == "running",
+ "you cannot stop a running status window if its not running"
+ )
+ self.state = "init"
+end
+
+return StatusWindow