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) isinstance(message.message, dict)
and message.message.get("type") == "thought" and message.message.get("type") == "thought"
and (text := message.message.get("text")) and (text := message.message.get("text"))
and isinstance(metadata := message.message.get("metadata"), dict) and (signature := message.message.get("signature"))
and (signature := metadata.get("signature"))
): ):
return { return {
"role": "assistant", "role": "assistant",

View File

@@ -642,15 +642,16 @@ class LLMThoughtEndFrame(ControlFrame):
"""Frame indicating the end of an LLM thought. """Frame indicating the end of an LLM thought.
Parameters: Parameters:
thought_metadata: Optional metadata associated with the thought, signature: Optional signature associated with the thought.
e.g. an Anthropic thought signature. 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): def __str__(self):
pts = format_pts(self.pts) 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 @dataclass

View File

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

View File

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