summaryrefslogtreecommitdiff
path: root/subagents/progress.lua
diff options
context:
space:
mode:
Diffstat (limited to 'subagents/progress.lua')
-rw-r--r--subagents/progress.lua53
1 files changed, 46 insertions, 7 deletions
diff --git a/subagents/progress.lua b/subagents/progress.lua
index d88e239..b39fe00 100644
--- a/subagents/progress.lua
+++ b/subagents/progress.lua
@@ -32,6 +32,7 @@ local GLYPHS = {
local M = {}
local boards = {}
+local background_workflows = {}
local bound = setmetatable({}, { __mode = "k" })
local tools_collapsed = true
local sid_width = 8
@@ -284,6 +285,11 @@ local function set_board_pinned(board, pinned)
end
end
+local function sync_board_pin(board)
+ local workflows = type(board.key) == "string" and background_workflows[board.key] or 0
+ set_board_pinned(board, board.tool_active or (workflows or 0) > 0)
+end
+
local function prune_boards()
for key, board in pairs(boards) do
if board.handle and board.handle.alive then
@@ -293,8 +299,16 @@ local function prune_boards()
end
end
-local function new_board()
- local board = { cards = {}, handle = nil, collapsed = tools_collapsed, next_sequence = 0, pinned = false }
+local function new_board(key)
+ local board = {
+ key = key,
+ cards = {},
+ handle = nil,
+ collapsed = tools_collapsed,
+ next_sequence = 0,
+ pinned = false,
+ tool_active = false,
+ }
board.component = { render = function(_, width) return render(board, width) end }
return board
end
@@ -305,7 +319,8 @@ function M.claim(event)
if not PROGRESS_TOOLS[name] then return end
if type(event.set_component) ~= "function" then return end
if type(event.collapsed) == "boolean" then tools_collapsed = event.collapsed end
- local key, board = event.id or event.tool_call_id or name, new_board()
+ local key = event.id or event.tool_call_id or name
+ local board = new_board(key)
local attached, handle = pcall(event.set_component, event, board.component)
if not attached then return end
board.handle = handle
@@ -317,20 +332,41 @@ function M.claim(event)
if replaying then
replay_board(board, type(key) == "string" and key or nil)
else
- set_board_pinned(board, true)
+ board.tool_active = true
end
+ sync_board_pin(board)
end
-- A result settles the outer tool invocation. Keep the board attached to its
--- transcript entry, but return it to that entry's original ordering.
+-- transcript entry, but leave it pinned while a background workflow it started
+-- is still running.
function M.settle(event)
local key = type(event) == "table" and (event.id or event.tool_call_id) or nil
local board = key and boards[key]
- if board then set_board_pinned(board, false) end
+ if board then
+ board.tool_active = false
+ sync_board_pin(board)
+ end
local co = coroutine.running()
if co and bound[co] == key then bound[co] = nil end
end
+function M.workflow_started(tool_call_id)
+ if type(tool_call_id) ~= "string" or tool_call_id == "" then return end
+ background_workflows[tool_call_id] = (background_workflows[tool_call_id] or 0) + 1
+ local board = boards[tool_call_id]
+ if board then sync_board_pin(board) end
+end
+
+function M.workflow_finished(tool_call_id)
+ if type(tool_call_id) ~= "string" or tool_call_id == "" then return end
+ local count = background_workflows[tool_call_id]
+ if count == nil then return end
+ if count <= 1 then background_workflows[tool_call_id] = nil else background_workflows[tool_call_id] = count - 1 end
+ local board = boards[tool_call_id]
+ if board then sync_board_pin(board) end
+end
+
function M.collapse(event)
if type(event.collapsed) ~= "boolean" then return end
prune_boards()
@@ -510,6 +546,8 @@ local function replay_turn(board, conv, messages, start, finish, info, agent, sy
local id = nonempty(info and info.id)
local model = nonempty(metadata and metadata.model) or nonempty(info and info.model)
+ local reasoning = nonempty(metadata and metadata.reasoning) or nonempty(info and info.reasoning)
+ if model and reasoning then model = model .. " (" .. reasoning .. ")" end
local card = new_card(board, agent or "subagent", id, model, {
prompt = prompt,
system_prompt = system_prompt,
@@ -727,7 +765,8 @@ end
function M.reset()
for _, board in pairs(boards) do
- set_board_pinned(board, false)
+ board.tool_active = false
+ sync_board_pin(board)
end
prune_boards()
-- `bound` has weak coroutine keys. Foreground handlers clear themselves in