v0.2.0
v0.2.0
Demo
▶ 89s background-task walkthrough (MP4)
Spawning a background subagent in a tmux pane, watching live tool-call progress in the parent pane, reading the final result via the session JSONL.
Changed
- Modular refactor of
src/. The single-fileindex.tsis now a thin wiring layer; the implementation is split across focused modules:src/tool/—renderCall,renderResult,taskComplete,prompt,schema.src/lifecycle/—polling,completion,toolStats,widget,restore.src/subagent/—buildArgv,runSdk,tmux,waitCompletion.src/conversation.ts—findJsonlSessionByName, registry andtask-session-historyhelpers.src/constants.ts—BACKGROUND_CHECK_MS,COUNT_POLL_MS,TASK_TIMEOUT_MS,MAX_POLL_ERRORS.src/types.ts—BackgroundTask,RegistryEntry,TaskSessionHistoryEntry,TaskDetails.
- Session JSONL is now the single source of truth for task results.
RESULT.mdis no longer read for completion detection or result text — the final assistant message in~/.pi/agent/sessions/.../<id>.jsonlis the authoritative result. This removes mid-writeEACCESand "stale truncatedRESULT.md" failure modes entirely. - Completion detection is gated on
stopReason.hasAgentFinished()insrc/session-text.tsonly treats an assistant message as final when itsstopReasonisstop,endTurn,length,error, oraborted.toolUsemid-turn streaming text is correctly ignored. - Background polling is hardened.
checkInFlightguard prevents overlapping poll ticks.MAX_POLL_ERRORS = 3per-task counter absorbs transient filesystem errors. Try/catch aroundcheckTaskCompletion()keeps the interval alive on one-off failures. - Reordered completion check flow. Session JSONL is consulted before pane liveness, so
remain-on-exitpanes no longer block detection.
Added
renderCall/renderResult/ task-complete renderers with Ctrl+O expand/collapse (viakeyHint("app.tools.expand")) on thetasktool. Foreground results show stats + preview; expanded shows the full result text. The keybinding hint falls back toCtrl+Oif theapp.tools.expandkeybinding is not registered.- Foreground real-time tool-call progress. The foreground
executepath now polls the session file and emits_onUpdatecallbacks while waiting, so the parent pane shows a live${n} tool callscount alongside the spawned subagent pane.
Fixed
- Duplicate "scout - Description" / "scout — Description" header in foreground results:
renderResultno longer re-renders the header thatrenderCallalready rendered. - The
( to expand)empty-keybinding hint: now falls back to a plainCtrl+O to expandlabel whenkeyText("app.tools.expand")is empty.
Verified
npm run typecheckpassesnpm run buildpassesnpm run smokepassesnpm pack --dry-runsucceeds (115.5 kB tarball, 61 files)