You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
4.4 KiB
Lua
199 lines
4.4 KiB
Lua
-- Agent registry module for nvim-claude
|
|
local M = {}
|
|
local utils = require('nvim-claude.utils')
|
|
|
|
-- Registry data
|
|
M.agents = {}
|
|
M.registry_path = nil
|
|
|
|
-- Initialize registry
|
|
function M.setup(config)
|
|
-- Set up registry directory
|
|
local data_dir = vim.fn.stdpath('data') .. '/nvim-claude'
|
|
utils.ensure_dir(data_dir)
|
|
|
|
M.registry_path = data_dir .. '/registry.json'
|
|
|
|
-- Load existing registry
|
|
M.load()
|
|
end
|
|
|
|
-- Load registry from disk
|
|
function M.load()
|
|
local content = utils.read_file(M.registry_path)
|
|
if content then
|
|
local ok, data = pcall(vim.json.decode, content)
|
|
if ok and type(data) == 'table' then
|
|
M.agents = data
|
|
M.validate_agents()
|
|
else
|
|
M.agents = {}
|
|
end
|
|
else
|
|
M.agents = {}
|
|
end
|
|
end
|
|
|
|
-- Save registry to disk
|
|
function M.save()
|
|
if not M.registry_path then return false end
|
|
|
|
local content = vim.json.encode(M.agents)
|
|
return utils.write_file(M.registry_path, content)
|
|
end
|
|
|
|
-- Validate agents (remove stale entries)
|
|
function M.validate_agents()
|
|
local valid_agents = {}
|
|
local now = os.time()
|
|
|
|
for id, agent in pairs(M.agents) do
|
|
-- Check if agent directory still exists
|
|
if utils.file_exists(agent.work_dir .. '/mission.log') then
|
|
-- Check if tmux window still exists
|
|
local window_exists = M.check_window_exists(agent.window_id)
|
|
|
|
if window_exists then
|
|
agent.status = 'active'
|
|
valid_agents[id] = agent
|
|
else
|
|
-- Window closed, mark as completed
|
|
agent.status = 'completed'
|
|
agent.end_time = agent.end_time or now
|
|
valid_agents[id] = agent
|
|
end
|
|
end
|
|
end
|
|
|
|
M.agents = valid_agents
|
|
M.save()
|
|
end
|
|
|
|
-- Check if tmux window exists
|
|
function M.check_window_exists(window_id)
|
|
if not window_id then return false end
|
|
|
|
local cmd = string.format("tmux list-windows -F '#{window_id}' | grep -q '^%s$'", window_id)
|
|
local result = os.execute(cmd)
|
|
return result == 0
|
|
end
|
|
|
|
-- Register a new agent
|
|
function M.register(task, work_dir, window_id, window_name)
|
|
local id = utils.timestamp() .. '-' .. math.random(1000, 9999)
|
|
local agent = {
|
|
id = id,
|
|
task = task,
|
|
work_dir = work_dir,
|
|
window_id = window_id,
|
|
window_name = window_name,
|
|
start_time = os.time(),
|
|
status = 'active',
|
|
project_root = utils.get_project_root(),
|
|
}
|
|
|
|
M.agents[id] = agent
|
|
M.save()
|
|
|
|
return id
|
|
end
|
|
|
|
-- Get agent by ID
|
|
function M.get(id)
|
|
return M.agents[id]
|
|
end
|
|
|
|
-- Get all agents for current project
|
|
function M.get_project_agents()
|
|
local project_root = utils.get_project_root()
|
|
local project_agents = {}
|
|
|
|
for id, agent in pairs(M.agents) do
|
|
if agent.project_root == project_root then
|
|
project_agents[id] = agent
|
|
end
|
|
end
|
|
|
|
return project_agents
|
|
end
|
|
|
|
-- Get active agents count
|
|
function M.get_active_count()
|
|
local count = 0
|
|
for _, agent in pairs(M.agents) do
|
|
if agent.status == 'active' then
|
|
count = count + 1
|
|
end
|
|
end
|
|
return count
|
|
end
|
|
|
|
-- Update agent status
|
|
function M.update_status(id, status)
|
|
if M.agents[id] then
|
|
M.agents[id].status = status
|
|
if status == 'completed' or status == 'failed' then
|
|
M.agents[id].end_time = os.time()
|
|
end
|
|
M.save()
|
|
end
|
|
end
|
|
|
|
-- Remove agent
|
|
function M.remove(id)
|
|
M.agents[id] = nil
|
|
M.save()
|
|
end
|
|
|
|
-- Clean up old agents
|
|
function M.cleanup(days)
|
|
if not days or days < 0 then return end
|
|
|
|
local cutoff = os.time() - (days * 24 * 60 * 60)
|
|
local removed = 0
|
|
|
|
for id, agent in pairs(M.agents) do
|
|
if agent.status ~= 'active' and agent.end_time and agent.end_time < cutoff then
|
|
-- Remove work directory
|
|
if agent.work_dir and utils.file_exists(agent.work_dir) then
|
|
local cmd = string.format('rm -rf "%s"', agent.work_dir)
|
|
utils.exec(cmd)
|
|
end
|
|
|
|
M.agents[id] = nil
|
|
removed = removed + 1
|
|
end
|
|
end
|
|
|
|
if removed > 0 then
|
|
M.save()
|
|
end
|
|
|
|
return removed
|
|
end
|
|
|
|
-- Format agent for display
|
|
function M.format_agent(agent)
|
|
local age = os.difftime(os.time(), agent.start_time)
|
|
local age_str
|
|
|
|
if age < 60 then
|
|
age_str = string.format('%ds', age)
|
|
elseif age < 3600 then
|
|
age_str = string.format('%dm', math.floor(age / 60))
|
|
elseif age < 86400 then
|
|
age_str = string.format('%dh', math.floor(age / 3600))
|
|
else
|
|
age_str = string.format('%dd', math.floor(age / 86400))
|
|
end
|
|
|
|
return string.format(
|
|
'[%s] %s (%s) - %s',
|
|
agent.status:upper(),
|
|
agent.task,
|
|
age_str,
|
|
agent.window_name or 'unknown'
|
|
)
|
|
end
|
|
|
|
return M |