Skip to content

Commit dcb3e28

Browse files
declan-scaleclaude
andcommitted
fix(claude-code): address Greptile review (num_llm_calls, dead code, session_id)
- TurnUsage.num_llm_calls is now Optional and defaults to None: it is provider-reported (from claude-code's num_turns) and may be absent, so None ("not reported") is distinct from a real 0. claude_code_usage_to_turn_usage returns None when num_turns is missing (real zeros still preserved). Counted fields (num_tool_calls / num_reasoning_blocks) stay int=0. - Removed a dead `full_text` assignment in the thinking content_block_stop path. - Added a public ClaudeCodeTurn.session_id accessor (mirrors CodexTurn) so the temporal activity no longer reaches into the private _result_envelope. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent eee3320 commit dcb3e28

5 files changed

Lines changed: 22 additions & 9 deletions

File tree

examples/tutorials/10_async/10_temporal/140_claude_code/project/activities.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,4 @@ async def run_claude_code_turn(params: RunClaudeCodeTurnParams) -> dict[str, Any
136136
turn = ClaudeCodeTurn(_spawn_claude(params.prompt, session_id=params.session_id))
137137
result = await emitter.auto_send_turn(turn, created_at=params.created_at)
138138

139-
session_id: str | None = None
140-
if getattr(turn, "_result_envelope", None):
141-
session_id = turn._result_envelope.get("session_id")
142-
143-
return RunClaudeCodeTurnResult(final_text=result.final_text, session_id=session_id).model_dump()
139+
return RunClaudeCodeTurnResult(final_text=result.final_text, session_id=turn.session_id).model_dump()

src/agentex/lib/adk/_modules/_claude_code_sync.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,6 @@ async def convert_claude_code_to_agentex_events(
341341

342342
elif se_type == "content_block_stop":
343343
if _thinking_open:
344-
full_text = _thinking_buf
345344
_thinking_open = False
346345
_thinking_buf = ""
347346
_pending_thinking_block_index = None

src/agentex/lib/adk/_modules/_claude_code_turn.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,11 @@ def _float(d: dict[str, Any], *keys: str) -> float | None:
8181
cost_usd = _float(result_envelope, "cost_usd", "total_cost_usd")
8282
duration_ms = _int(result_envelope, "duration_ms")
8383

84+
# num_llm_calls is provider-reported (from num_turns): default None ("not
85+
# reported") rather than 0 so callers can distinguish it from a real zero,
86+
# matching the None convention used for the token fields above.
8487
num_turns = result_envelope.get("num_turns")
85-
num_llm_calls = 0
88+
num_llm_calls: int | None = None
8689
if num_turns is not None:
8790
try:
8891
num_llm_calls = int(num_turns)
@@ -129,6 +132,18 @@ def events(self) -> AsyncIterator[StreamTaskMessage]:
129132
)
130133
return self._events_stream
131134

135+
@property
136+
def session_id(self) -> str | None:
137+
"""The Claude Code session id, for resuming a multi-turn session.
138+
139+
Valid only after ``events`` has been fully consumed (populated by the
140+
``result`` envelope). Returns ``None`` if the stream was truncated or
141+
Claude Code reported no session id.
142+
"""
143+
if not self._result_envelope:
144+
return None
145+
return self._result_envelope.get("session_id")
146+
132147
def usage(self) -> TurnUsage:
133148
"""Return normalised usage for this turn.
134149

src/agentex/lib/core/harness/types.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ class TurnUsage(BaseModel):
6464
total_tokens: int | None = None
6565
cost_usd: float | None = None
6666
duration_ms: int | None = None
67-
num_llm_calls: int = 0
67+
# num_llm_calls is provider-reported and may be absent (None = "not
68+
# reported"). num_tool_calls / num_reasoning_blocks are counted locally from
69+
# the observed stream, so 0 is always a real count.
70+
num_llm_calls: int | None = None
6871
num_tool_calls: int = 0
6972
num_reasoning_blocks: int = 0
7073

tests/lib/adk/test_claude_code_turn.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def test_missing_usage_key_returns_nones(self):
8484
assert usage.total_tokens is None
8585
assert usage.cost_usd is None
8686
assert usage.duration_ms is None
87-
assert usage.num_llm_calls == 0
87+
assert usage.num_llm_calls is None
8888

8989
def test_real_zeros_preserved(self):
9090
result = {

0 commit comments

Comments
 (0)