diff options
Diffstat (limited to 'subagents/progress.lua')
| -rw-r--r-- | subagents/progress.lua | 53 |
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 |
