fix(claudecode): a message's content is a string or a list, not only a list - #7
Merged
Merged
Conversation
…a list The decoder modelled message.content as a list of content blocks. Claude Code emits it as a bare string too — the same string-or-blocks polymorphism a tool result's own content already has, one level up — and json.Unmarshal returned an error for the shape it did not model. Decode returns that error, so one such line failed the whole run. It reached the caller as ErrProviderUnavailable: a stream that was working, reported as the CLI being unreachable, which invites a retry that fails the same way. Both shapes are accepted now, and neither is required: a null content leaves the fields zero rather than failing a line carrying no message body. The string form of an assistant message is the answer itself, so it surfaces as text; the string form of a user message is the prompt echoed rather than a tool answering, so it yields nothing, as an unmodelled line does.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
claudecode's decoder modelsmessage.contentas a list of content blocks. Claude Code also emits it as a bare string, andjson.Unmarshalreturns an error for the shape it does not model.Decodereturns that error, so one such line fails the entire run:The failure surfaces as
ErrProviderUnavailable— a stream that was working, reported as the CLI being unreachable, which invites a retry that fails identically.Why the existing tolerance didn't cover it
Decode's doc says a line whose type this package does not model "is not a reason to fail a run that is working". That tolerance is keyed on the event type. A known type carrying a polymorphic field falls straight through it and reaches thejson.Unmarshalerror return at the top of the function.The package already knows this exact polymorphism:
toolResultTextaccepts string-or-blocks for a tool result's own content, andstreamEvent's doc comment explains why. The same shape occurs one level up, on the message itself.The change
message.contentis decoded through a type accepting either shape, and neither — a null content leaves both fields zero rather than failing a line carrying no message body.EventKindTextevent rather than being dropped.How it was found
agtk memory curatedied mid-run againstv0.3.0. The store was left untouched, but the run was lost. Reproduced hermetically throughagentictest.Fake, with no model call:Each new test was confirmed to fail before the change. Verified downstream by pointing agentic-toolkit at this branch with a
replacedirective: the failing case passes, and the directive was dropped again rather than committed.Impact
claudecodeis the only provider that can perform a real curation run, so onv0.3.0this breaksagtk memory curateon the default provider whenever such a line appears.