#3150 reworded write_file's description, overwrite parameter, and guard
error to prefer append_file/edit_file. But those tools register via their
own enable flags and the per-agent allowlist, so a config exposing only
write_file was steered toward tools it does not have — a dead end in the
most restrictive setups.
WriteFileTool now tracks which non-destructive alternatives are available
and names only the ones present; when none are, the guard still blocks the
overwrite without pointing anywhere. The agent wiring registers the editors
before write_file and resolves availability via registry.HasRegistered,
which reflects both the enable flag and the allowlist.
Tests: conditional copy at the tool level (none/one/both) and agent wiring
across the enable-flag and allowlist dimensions.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ToolCall.Name and .Arguments are json:"-" (runtime-only), so after chat
history round-trips through the session store only ToolCall.Function
survives. The anthropic-messages and anthropic (SDK) providers emitted
tool_use blocks from tc.Name alone, silently skipping every historical
tool call while still emitting the matching tool_result — orphaned
tool_results 400 at the API ("unexpected tool_use_id found in
tool_result blocks"), killing every turn on agents with tool history.
Fall back to Function.Name / json-parsed Function.Arguments (the same
pattern the bedrock and openai_compat providers already use), and cover
the deserialized-history shape with table tests in both providers.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The overwrite guard error ("Set overwrite=true to replace") steered the
model to clobber files like MEMORY.md. Reword write_file's description,
overwrite param, and guard error to prefer append_file/edit_file.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address review feedback: the routed-agent /clear path bypassed the
public ContextManager.Clear contract via an unexported hook. Restore
the single Clear call in the command path and resolve the session's
owning agent inside the built-in implementations instead:
- legacy: Clear resolves the owning agent via agentForSession instead
of assuming the default agent
- seahorse: drop ClearContextStore; Clear wipes the engine state and
the owning agent's session store
- command path: persist session scope metadata before Clear so
ownership resolves even when /clear is the session's first message
- add coverage that a custom ContextManager receives Clear for routed
agents
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Previously when io.Copy to the base64 encoder failed, encoder.Close()
was skipped. This left the encoder's internal buffer unflushed.
Now always call Close() and handle both copy and close errors
explicitly.
Two bugs prevented the usage block from ever reaching the wire:
1. CallLLM read turnStateFromContext(ctx), but the raw ctx is not seeded
with the turn state (only turnCtx is), so SetLastUsage/SetLastFinishReason
were dropped — GetLastUsage() returned nil at finalize. Set them on the
ts parameter directly, which is also what the streaming publisher reads.
2. The manager wraps the channel streamer in finalizeHookStreamer /
splitMarkerStreamer, neither of which forwarded SetTurnUsage (it is not
part of the bus.Streamer interface), so the type assertion in the
publisher's Finalize failed silently. Mirror the existing SetModelName
forwarding: add a turnUsageStreamer interface + setStreamerTurnUsage
helper and SetTurnUsage methods on both wrappers (splitMarker also stores
and re-applies usage to each freshly-begun part streamer).
Adds regression tests asserting both wrappers forward SetTurnUsage.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>