diff options
| -rw-r--r-- | README.md | 20 | ||||
| -rw-r--r-- | _selfcheck.lua | 22 | ||||
| -rw-r--r-- | panto-herdr/init.lua | 51 |
3 files changed, 66 insertions, 27 deletions
@@ -26,20 +26,16 @@ its JSON output, so reporting does not affect the panto terminal UI. | panto event | Herdr state | | --- | --- | -| `session_start`, `session_ready` | `idle` | -| `user_message`, `thinking`, `compaction`, `tool_details`, `assistant_text` | `working` | -| `assistant_text_complete` | `idle` | +| `session_start`, `session_ready` | `idle` when no work is active | +| `turn_start`, `agent_submission`, `user_message`, `thinking`, `compaction`, `tool_details`, `assistant_text` | `working` | +| `turn_end` | `idle` when no background work is active | +| `background_work_start` / `background_work_end` | increments / decrements active background work | | `session_end` | agent released | -`session_ready` restores `idle` after panto replays historical lifecycle events -while loading a resumed session. `session_end` removes panto's agent report when -the process shuts down, so Herdr also clears the pane/space activity indicator -once no reported agents remain. - -`assistant_text_complete` is the block-level idle boundary; an assistant text -block followed by a tool call can show `idle` briefly before the next lifecycle -event restores `working`. Native session restore is out of scope until panto -exposes a stable session reference to extensions. +Extensions with work that survives a turn emit balanced `background_work_start` +and `background_work_end` events. Herdr remains `working` until both the primary +turn and all such work finish. `session_end` removes panto's agent report when +the process shuts down. ## Check diff --git a/_selfcheck.lua b/_selfcheck.lua index 08df12c..cb479d6 100644 --- a/_selfcheck.lua +++ b/_selfcheck.lua @@ -50,7 +50,12 @@ events.user_message() events.user_message() events.tool_details({ tool_name = "read" }) events.assistant_text() -events.assistant_text_complete() +events.background_work_start() +events.turn_end() +events.agent_submission() +events.background_work_end() +events.assistant_text() +events.turn_end() events.session_end() -- A new process in the same pane/source must outrank the old process's final @@ -61,15 +66,18 @@ entry.activate() events.session_start() events.assistant_text() events.session_ready() +events.turn_end() -assert(#reports == 9) +assert(#reports == 12) assert(reports[1].command == "herdr") assert(table.concat(reports[1].args, " ") == "pane report-agent w1:p1 --source panto:extension --agent panto --state idle --seq 100000001") assert(table.concat(reports[3].args, " ") == "pane report-agent w1:p1 --source panto:extension --agent panto --state working --seq 100000003 --message tool:read") -assert(table.concat(reports[5].args, " ") == "pane report-agent w1:p1 --source panto:extension --agent panto --state idle --seq 100000005") -assert(table.concat(reports[6].args, " ") == "pane release-agent w1:p1 --source panto:extension --agent panto --seq 100000006") -assert(table.concat(reports[7].args, " ") == "pane report-agent w1:p1 --source panto:extension --agent panto --state idle --seq 101000001") -assert(table.concat(reports[8].args, " ") == "pane report-agent w1:p1 --source panto:extension --agent panto --state working --seq 101000002 --message responding") -assert(table.concat(reports[9].args, " ") == "pane report-agent w1:p1 --source panto:extension --agent panto --state idle --seq 101000003") +assert(table.concat(reports[5].args, " ") == "pane report-agent w1:p1 --source panto:extension --agent panto --state working --seq 100000005 --message background") +assert(table.concat(reports[6].args, " ") == "pane report-agent w1:p1 --source panto:extension --agent panto --state working --seq 100000006 --message thinking") +assert(table.concat(reports[8].args, " ") == "pane report-agent w1:p1 --source panto:extension --agent panto --state idle --seq 100000008") +assert(table.concat(reports[9].args, " ") == "pane release-agent w1:p1 --source panto:extension --agent panto --seq 100000009") +assert(table.concat(reports[10].args, " ") == "pane report-agent w1:p1 --source panto:extension --agent panto --state idle --seq 101000001") +assert(table.concat(reports[11].args, " ") == "pane report-agent w1:p1 --source panto:extension --agent panto --state working --seq 101000002 --message responding") +assert(table.concat(reports[12].args, " ") == "pane report-agent w1:p1 --source panto:extension --agent panto --state idle --seq 101000003") print("panto-herdr self-check: ok") diff --git a/panto-herdr/init.lua b/panto-herdr/init.lua index cc0b527..b3d30be 100644 --- a/panto-herdr/init.lua +++ b/panto-herdr/init.lua @@ -17,6 +17,9 @@ return { local seq = os.time() * 1000000 local last_state local last_status + local foreground_working = false + local foreground_status + local background_work = 0 local function spawn(args) local handle @@ -57,16 +60,48 @@ return { }) end - panto.ext.on("session_start", function() report("idle") end) - panto.ext.on("session_ready", function() report("idle") end) - panto.ext.on("user_message", function() report("working", "thinking") end) - panto.ext.on("thinking", function() report("working", "thinking") end) - panto.ext.on("compaction", function() report("working", "compacting") end) + local function update_idle_state() + if foreground_working or background_work > 0 then + report("working", foreground_working and foreground_status or "background") + else + report("idle") + end + end + + local function foreground(status) + foreground_working, foreground_status = true, status + report("working", status) + end + + panto.ext.on("session_start", function() + foreground_working, foreground_status, background_work = false, nil, 0 + report("idle") + end) + panto.ext.on("session_ready", function() + foreground_working, foreground_status = false, nil + update_idle_state() + end) + panto.ext.on("turn_start", function() foreground("thinking") end) + panto.ext.on("agent_submission", function() foreground("thinking") end) + panto.ext.on("user_message", function() foreground("thinking") end) + panto.ext.on("thinking", function() foreground("thinking") end) + panto.ext.on("compaction", function() foreground("compacting") end) panto.ext.on("tool_details", function(event) - report("working", tool_status(event.tool_name)) + foreground(tool_status(event.tool_name)) + end) + panto.ext.on("assistant_text", function() foreground("responding") end) + panto.ext.on("turn_end", function() + foreground_working, foreground_status = false, nil + update_idle_state() + end) + panto.ext.on("background_work_start", function() + background_work = background_work + 1 + update_idle_state() + end) + panto.ext.on("background_work_end", function() + background_work = math.max(0, background_work - 1) + update_idle_state() end) - panto.ext.on("assistant_text", function() report("working", "responding") end) - panto.ext.on("assistant_text_complete", function() report("idle") end) panto.ext.on("session_end", release) end, } |
