fix(streaming): forward tool args on execution-end event#477
Conversation
The tool result callback hardcoded an empty args dict for completed tools,
so renderers that derive their display from args (e.g. the read_file panel's
filename/path) fell back to the literal "unknown". Forward event_obj.args
instead. It is None-safe and harmlessly yields {} on tinyagent builds that
do not yet populate the field, and lights up automatically once they do.
Depends on tinyagent exposing `args` on ToolExecutionEndEvent
(alchemiststudiosDOTai/tinyAgent#43).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📜 Recent review details⏰ Context from checks skipped due to timeout. (1)
|
| Layer / File(s) | Summary |
|---|---|
Forward event args to callback src/tunacode/core/agents/agent_components/agent_streaming.py |
tool_result_callback now receives event_obj.args or {} instead of a hardcoded empty dict, while tool name/status/result/duration handling is unchanged. |
Estimated code review effort: 1 (Trivial) | ~3 minutes
Possibly related issues
- ToolExecutionEndEvent is missing
argsfield (present on Start/Update events) tinyAgent#43: AddressesToolExecutionEndEvent.argspresence at the event source, which this PR's callback change now consumes — flag as a dependency: if the upstream event doesn't reliably populateargs, this fix is a no-op or silently passes stale/empty data. - alchemiststudiosDOTai/tinyAgent#42: Directly tied to the same
ToolExecutionEndEvent.argsfield this change relies on; verify the field's type/default contract matches theevent_obj.args or {}fallback logic here to avoid masking upstream bugs (e.g.,Nonevs missing attribute vs empty dict semantics differ).
Note: this is a one-line diff, but the fallback event_obj.args or {} silently swallows falsy-but-valid args (e.g., an empty dict passed intentionally is indistinguishable from None). If CLAUDE.md has a gate on explicit None-checks for event payloads rather than truthy-fallback (common in this codebase's defensive-coding guidance), this should be event_obj.args if event_obj.args is not None else {} instead.
🚥 Pre-merge checks | ✅ 9
✅ Passed checks (9 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | ✅ Passed | The title uses a valid fix conventional-commit prefix and accurately describes the streaming tool-args change. |
| Description check | ✅ Passed | The description covers what, why, safety, and dependency, so it is substantially complete despite missing template checklist sections. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
| Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Noshallowcopymutation | ✅ Passed | No .copy()-then-nested-mutation pattern exists in the touched streaming handler; the PR only forwards event_obj.args or {}. |
| Exceptionpathcleanup | ✅ Passed | PASS: agent_streaming.py cleans up in its CancelledError/Exception handler via _handle_interrupted_stream_cleanup(); this PR only forwards args and doesn’t alter exception paths. |
| Dependencydirection | ✅ Passed | PASS: Gate 2 holds—this core file imports stdlib/tinyagent/core/utils/types only; no ui/ or tools/ imports, and no types/ module changes. |
| Nosilentfailures | ✅ Passed | PASS: The diff only swaps {} for event_obj.args or {}; no added empty excepts, swallowed exceptions, or silent return None paths in the touched handler. |
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
What
Forward the tool-call arguments on the streaming tool-execution-end handler
instead of hardcoding an empty dict.
self.tool_result_callback( tool_name, status, - {}, + event_obj.args or {}, event_obj.result, duration_ms, )Why
For completed tools,
_handle_stream_tool_execution_endpassed{}as the argsto
tool_result_callback. Per-tool renderers that derive their panel displayfrom args therefore had nothing to work with. The most visible symptom: the
read_fileresult panel builds its filename/path solely fromargs["filepath"], so with empty args it rendered the literal string"unknown"in the tool-output bar for every successful read.Safety / compatibility
event_obj.args or {}is None-safe. On a tinyagent build whereToolExecutionEndEventdoes not carryargs,event_obj.argsisNoneand theexpression yields
{}— identical to today's behaviour, no regression. Oncetinyagent populates the field, the real filepath flows through automatically with
no further change here.
Dependency
The end-to-end fix needs tinyagent to expose
argsonToolExecutionEndEvent(it currently only lives on the Start/Update events). Tracked upstream in
alchemiststudiosDOTai/tinyAgent#43. This PR is the consumer half and is safe to
merge independently ahead of that.
Updated streaming tool execution end handling so
tool_result_callbacknow receivesevent_obj.args or {}instead of a hardcoded empty dict.This preserves state needed by per-tool renderers and message/tool-call output (for example, allowing completed
read_filecalls to surface their filepath instead of"unknown"), while remaining safe whenToolExecutionEndEvent.argsis unavailable.Type safety is unchanged functionally, but the new
None-fallback avoids regressions on builds that have not yet adopted the upstream event field.