Simplify, at the expense of a bit of not-yet-needed flexibility: rather than associating a loose thought_metadata with each thought, use a signature. Thought signatures are the only "thought metadata" we use today.

This commit is contained in:
Paul Kompfner
2025-12-04 14:47:31 -05:00
parent c8c6f424cd
commit 15f5583fd2
4 changed files with 8 additions and 12 deletions

View File

@@ -185,8 +185,7 @@ class AnthropicLLMAdapter(BaseLLMAdapter[AnthropicLLMInvocationParams]):
isinstance(message.message, dict)
and message.message.get("type") == "thought"
and (text := message.message.get("text"))
and isinstance(metadata := message.message.get("metadata"), dict)
and (signature := metadata.get("signature"))
and (signature := message.message.get("signature"))
):
return {
"role": "assistant",

View File

@@ -642,15 +642,16 @@ class LLMThoughtEndFrame(ControlFrame):
"""Frame indicating the end of an LLM thought.
Parameters:
thought_metadata: Optional metadata associated with the thought,
e.g. an Anthropic thought signature.
signature: Optional signature associated with the thought.
This is used by Anthropic, which includes a signature at the end of
each thought.
"""
thought_metadata: Optional[Dict[str, Any]] = None
signature: Any = None
def __str__(self):
pts = format_pts(self.pts)
return f"{self.name}(pts: {pts}, metadata: {self.thought_metadata})"
return f"{self.name}(pts: {pts}, signature: {self.signature})"
@dataclass

View File

@@ -905,7 +905,7 @@ class LLMAssistantAggregator(LLMContextAggregator):
message={
"type": "thought",
"text": thought,
"metadata": frame.thought_metadata,
"signature": frame.signature,
},
)
)

View File

@@ -421,11 +421,7 @@ class AnthropicLLMService(LLMService):
elif hasattr(event.delta, "thinking"):
await self.push_frame(LLMThoughtTextFrame(text=event.delta.thinking))
elif hasattr(event.delta, "signature"):
await self.push_frame(
LLMThoughtEndFrame(
thought_metadata={"signature": event.delta.signature}
)
)
await self.push_frame(LLMThoughtEndFrame(signature=event.delta.signature))
elif event.type == "content_block_start":
if event.content_block.type == "tool_use":
tool_use_block = event.content_block