Skip to content

fix: read the code execution tool's shell calls as code execution activity - #26

Closed
dtmeadows-ant wants to merge 2 commits into
trilorez/xcode-27-beta-5from
dmeadows/bash-code-execution-activity
Closed

fix: read the code execution tool's shell calls as code execution activity#26
dtmeadows-ant wants to merge 2 commits into
trilorez/xcode-27-beta-5from
dmeadows/bash-code-execution-activity

Conversation

@dtmeadows-ant

Copy link
Copy Markdown
Contributor

Follow-up to #24, targeting its branch.

With .codeExecution enabled, code_execution_20260120 answers with server_tool_use name=bash_code_execution (input command) → bash_code_execution_tool_result. The typed reading only matched plain code_execution / {code} / code_execution_tool_result, so every code-execution activity surfaced as .unrecognized("bash_code_execution", …). Plain code_execution blocks do still appear — other server tools (web search) emit them when they run code internally — so both names need to read as .codeExecution.

This accepts either name, decodes code or command, expects <name>_tool_result, and has activity.toolName report whichever it was. text_editor_code_execution stays .unrecognized. No public API change.

Verified on Xcode 27 beta 5 / iOS 27 beta 5 simulator: 212/212, and live a .codeExecution session now yields .codeExecution with toolName == "bash_code_execution" and .output(stdout:…), with the follow-up turn replaying fine.

trilorez and others added 2 commits August 12, 2026 16:55
…nt them

Xcode 27 beta 5 removes `Transcript.CustomSegment`, which this package
used to keep server-side tool calls and results (web search, web fetch,
code execution) on the transcript. That storage is replaced, and replay
of earlier assistant turns is rebuilt on top of the replacement so that
everything the Messages API requires back verbatim actually goes back
verbatim.

How it works now:
- As a turn streams, every completed content block is recorded, as the
  API sent it, in the metadata of the transcript entry that presents
  it: a thinking block on its reasoning entry, a tool_use block on its
  tool call, and text, server-tool traffic and anything unrecognized on
  the response entry. Each record carries the turn it belongs to and
  each block its position in that turn.
- Building the next request, a turn's recorded blocks are replayed in
  position order, so thinking signatures, server tool results and
  citations return exactly as received however the framework's entries
  interleave. Entries with no record (an app-assembled transcript, an
  entry cut off before its first block completed) are rebuilt from
  their segments and signature. Tool calls and results the API would
  reject as unpaired, and turns left with nothing but thinking, are
  dropped instead of failing every later request.
- Records are key-sorted JSON text under a reserved `claude.content`
  metadata key and survive `Transcript` persistence unchanged.

Public API:
- `ClaudeServerToolSegment` and its transcript accessors are removed.
  `ClaudeServerToolActivity` replaces them: typed web search / web
  fetch / code execution readings, or `.unrecognized` by tool name.
- A response entry's segments run in the order the model produced them:
  one text segment per text block, and wherever the model called a
  server-side tool, an empty text segment whose id is the tool-use id
  holding that call's place. `Transcript.Response
  .claudeServerToolActivity(for:)` resolves such a segment to its
  activity so apps can render searches inline between paragraphs;
  `Transcript.claudeServerToolActivity` lists every round-trip in a
  conversation and pairs results that arrive in a later response.

Also:
- `pause_turn` responses are continued automatically, with
  usage accumulated across the continuation and trailing whitespace
  trimmed from the re-sent content as the API requires.
- `ContentBlock` decodes any untyped block losslessly as `.raw`;
  `content_block_start` carries the block as sent; a `ContentAssembler`
  in ClaudeAPI rebuilds streamed blocks into their non-streaming form.
- An App Attest token rejected on a continuation request is refreshed
  and retried like one rejected on the first request.

Fixes #23
…ivity

The code execution tool answers with `bash_code_execution` calls (input
`command`, result `bash_code_execution_tool_result`), which the typed
reading didn't match, so every code-execution activity surfaced as
`.unrecognized`. Accept that name alongside plain `code_execution` and
report whichever it was from `toolName`.
@trilorez

Copy link
Copy Markdown
Collaborator

Folded into #24 (28c8d2d), with toolName exposed on CodeExecution. Thanks!

@trilorez trilorez closed this Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants