Pi sometimes sends tool results as a direct array [{"type":"text","text":"..."}]
rather than wrapped in {"content": [...]}. Now handles both formats to
properly extract text content instead of showing raw JSON.
Pi returns tool results in format: {"content": [{"type": "text", "text": "..."}]}
Previously we were JSON.stringify-ing the whole object, showing as:
{"content":[{"type":"text","text":"..."}]}
Now we extract the actual text content for cleaner display.
The turn_end event includes toolResults array with toolName. Previously
the parsing only included toolCallId, now we also extract toolName so
the UI can display the correct tool name even when tool_result entries
arrive without a preceding tool_call.
When tool_result entries arrive without a matching tool_call, the transcript
was showing generic 'tool' as the name. Now pl-local parses toolName from
tool_execution_end events and passes it through, so the UI can display
the actual tool name (e.g., 'bash', 'Read', 'Ls') instead of 'tool'.
Major improvements to the Pi local adapter:
Bug Fixes (Greptile-identified):
- Fix string interpolation in models.ts error message (was showing literal ${detail})
- Fix tool matching in parse.ts to use toolCallId instead of toolName for correct
multi-call handling and result assignment
- Fix dead code in execute.ts by tracking instructionsReadFailed flag
Feature Improvements:
- Switch from print mode (-p) to RPC mode (--mode rpc) to prevent agent from
exiting prematurely and ensure proper lifecycle completion
- Add stdin command sending via JSON-RPC format for prompt delivery
- Add line buffering in execute.ts to handle partial JSON chunks correctly
- Filter RPC protocol messages (response, extension_ui_request, etc.) from transcript
Cost Tracking:
- Extract cost and usage data from turn_end assistant messages
- Support both Pi format (input/output/cacheRead/cost.total) and generic format
- Add tests for cost extraction and accumulation across multiple turns
All tests pass (12/12), typecheck clean, server builds successfully.