diff options
| author | Igor Soarez <igor@soarez.org> | 2026-10-27 14:12:28 +0200 |
|---|---|---|
| committer | Igor Soarez <igor@soarez.org> | 2026-10-27 14:12:28 +0200 |
| commit | 50c433e82c368b9861a89deecb74e5f29fa50353 (patch) | |
| tree | fe6d87b79387f6c53ef9bf615b7b530daf9a8d3a /crates/dinggerd/assets/pi | |
| parent | 9f3a567d4bb1b7b6e42a744936f993bcd437882d (diff) | |
mark as unread: make an idle agent done again, to come back to it
like "mark as unread" in mail: an agent you have seen (idle) becomes done
again, last among done agents of its importance, with no sound or
notification. it stays done until you come back to it: leave its tmux
window and return, or jump to it. marked while you look at it, it holds
until you look away (`held`); a new turn clears it. only idle agents can
be marked.
- daemon: `pane.mark_unread` on the hook socket; the watcher applies it
after the tick's observations (mark_unread, advance's hold rule).
- `dingger unread [--pane]`: refuses done, working, blocked, and panes
without an agent; returns once the agent shows as done.
- pi: /unread (refused while the agent works or is blocked).
- panel: right-click an idle agent in the full list, "Mark as unread".
- search: ⌘U or right-click marks the selected idle agent; the footer
offers ⌘U when it applies; search stays open.
tests: unit (hold, jump, new turn, idle only), e2e step 22 (queue
position, hold, look away and back, jump, refusals, no sound, menu, the
extension), pi-live in real pi 1.4 (a mark, not a turn: an unknown
command would also end done), swift selftest (menu only for idle, footer).
Diffstat (limited to 'crates/dinggerd/assets/pi')
| -rw-r--r-- | crates/dinggerd/assets/pi/pi-agent-state.ts | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/crates/dinggerd/assets/pi/pi-agent-state.ts b/crates/dinggerd/assets/pi/pi-agent-state.ts index 4c21afe..0719265 100644 --- a/crates/dinggerd/assets/pi/pi-agent-state.ts +++ b/crates/dinggerd/assets/pi/pi-agent-state.ts @@ -47,11 +47,12 @@ function sendRequestAttempt(request: unknown, timeoutMs: number): Promise<boolea }); } -async function sendRequest(request: unknown): Promise<void> { +// Whether the daemon got it. +async function sendRequest(request: unknown): Promise<boolean> { if (await sendRequestAttempt(request, 500)) { - return; + return true; } - await sendRequestAttempt(request, 1500); + return sendRequestAttempt(request, 1500); } type AgentState = "working" | "blocked" | "idle"; @@ -96,9 +97,13 @@ function savedImportance(ctx: any): Importance { return "normal"; } -function report(state: AgentState | undefined, message?: string): Promise<void> { - return sendRequest({ - id: `${source}:${Date.now()}:${Math.random().toString(36).slice(2)}`, +function requestId(): string { + return `${source}:${Date.now()}:${Math.random().toString(36).slice(2)}`; +} + +async function report(state: AgentState | undefined, message?: string): Promise<void> { + await sendRequest({ + id: requestId(), method: "pane.report_agent", params: { pane_id: paneId!, @@ -226,6 +231,28 @@ export default function (pi) { }, }); + // Like "mark as unread" in mail: dingger shows the agent as done again + // (a pane option; nothing is saved in the session). + pi.registerCommand("unread", { + description: "Mark this agent unread in dingger: it shows as done until you come back to it", + handler: async (_args: string, ctx: any) => { + if (agentActive || blockedCount > 0) { + ctx.ui.notify("only an idle agent can be marked unread", "error"); + return; + } + const delivered = await sendRequest({ + id: requestId(), + method: "pane.mark_unread", + params: { pane_id: paneId! }, + }); + if (delivered) { + ctx.ui.notify("marked unread: dingger shows it as done until you come back to it", "info"); + } else { + ctx.ui.notify("dingger is not running", "error"); + } + }, + }); + pi.on("session_start", async (event, ctx) => { // TUI only: RPC/JSON/print modes are headless. if (ctx?.mode !== "tui") { |
