repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
neovim/lua/bugabinga/pivi/status.lua
Rawlocal copy = function( state )
local next_state = vim.deepcopy( state )
return next_state
end
local initial = function()
return {
connection = 'starting',
run = 'idle',
tool = nil,
queue = { steering = {}, follow_up = {}, },
compacting = false,
retry = nil,
error = nil,
model = nil,
thinking = nil,
session = nil,
context = nil,
exit_code = nil,
}
end
--- Folds one RPC event into cached semantic status.
--- Pure: no editor state is read or written here.
--- @param state table current status
--- @param event table one RPC event
--- @return table state the next status
local reduce = function( state, event )
if type( event ) ~= 'table' or type( event.type ) ~= 'string' then return state end
local next_state = copy( state )
local kind = event.type
if kind == 'agent_start' then
next_state.connection = 'running'
next_state.run = 'running'
next_state.error = nil
elseif kind == 'agent_end' then
next_state.run = event.willRetry and 'retrying' or 'running'
elseif kind == 'agent_settled' then
next_state.run = 'idle'
next_state.tool = nil
next_state.retry = nil
elseif kind == 'tool_execution_start' then
next_state.run = 'running'
next_state.tool = { id = event.toolCallId, name = event.toolName, }
elseif kind == 'tool_execution_end' then
if next_state.tool and next_state.tool.id == event.toolCallId then next_state.tool = nil end
elseif kind == 'queue_update' then
next_state.queue = {
steering = event.steering or {},
follow_up = event.followUp or {},
}
elseif kind == 'compaction_start' then
next_state.compacting = true
elseif kind == 'compaction_end' then
next_state.compacting = false
if event.errorMessage then next_state.error = event.errorMessage end
elseif kind == 'auto_retry_start' then
next_state.run = 'retrying'
next_state.retry = { attempt = event.attempt, max = event.maxAttempts, delay = event.delayMs, }
next_state.error = event.errorMessage
elseif kind == 'auto_retry_end' then
next_state.retry = nil
if event.success then
next_state.run = 'running'
next_state.error = nil
else
next_state.run = 'idle'
next_state.error = event.finalError
end
elseif kind == 'extension_error' then
next_state.error = event.error
elseif kind == 'message_end' then
local message = event.message
if message and message.errorMessage then next_state.error = message.errorMessage end
end
return next_state
end
--- Folds a `get_state` response payload into cached status.
local reduce_state = function( state, data )
if type( data ) ~= 'table' then return state end
local next_state = copy( state )
next_state.connection = 'running'
next_state.model = data.model and data.model.id or next_state.model
next_state.thinking = data.thinkingLevel or next_state.thinking
next_state.session = {
id = data.sessionId,
name = data.sessionName,
file = data.sessionFile,
messages = data.messageCount,
}
if data.isStreaming ~= nil and next_state.run == 'idle' and data.isStreaming then
next_state.run = 'running'
end
next_state.compacting = data.isCompacting == true
return next_state
end
--- Folds a `get_session_stats` response payload into cached status.
local reduce_stats = function( state, data )
if type( data ) ~= 'table' then return state end
local next_state = copy( state )
local usage = data.contextUsage
if usage then
next_state.context = {
tokens = usage.tokens,
window = usage.contextWindow,
percent = usage.percent,
}
end
next_state.cost = data.cost
return next_state
end
local stopped = function( state, exit_code )
local next_state = copy( state )
next_state.connection = 'stopped'
next_state.run = 'idle'
next_state.tool = nil
next_state.exit_code = exit_code
return next_state
end
local is_busy = function( state )
return state.run == 'running' or state.run == 'retrying' or state.compacting == true
end
local pending_count = function( state )
return #( state.queue.steering or {} ) + #( state.queue.follow_up or {} )
end
--- Short human summary suitable for a statusline.
local summary = function( state )
if state.connection == 'stopped' then return 'pi:off' end
if state.run == 'retrying' then return 'pi:retry' end
if state.error then return 'pi:error' end
if state.compacting then return 'pi:compacting' end
if state.tool then return 'pi:' .. tostring( state.tool.name ) end
if state.run == 'running' then return 'pi:run' end
local pending = pending_count( state )
if pending > 0 then return 'pi:idle+' .. tostring( pending ) end
return 'pi:idle'
end
return {
initial = initial,
reduce = reduce,
reduce_state = reduce_state,
reduce_stats = reduce_stats,
stopped = stopped,
is_busy = is_busy,
pending_count = pending_count,
summary = summary,
}