Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-relay/src/lexigram/ai/relay/mappers/claude/utils.py: 50%

20 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-25 07:19 +0800

1"""Shared parsing/serialization helpers for the Claude mapper.""" 

2 

3from __future__ import annotations 

4 

5from typing import Any 

6 

7from lexigram.ai.relay.mappers.base import new_uuid 

8from lexigram.contracts.ai.llm import FunctionCall, ToolCall 

9from lexigram.contracts.ai.relay.dto import ClaudeContent 

10from lexigram.contracts.ai.relay.types import RelayFormat 

11from lexigram.serialization import loads_str 

12 

13_TARGET = RelayFormat.CLAUDE 

14 

15 

16def _tool_call_from_block(block: ClaudeContent) -> ToolCall: 

17 """Convert a Claude ``tool_use`` block into a canonical ``ToolCall``.""" 

18 return ToolCall( 

19 id=block.tool_use_id or "", 

20 type="custom", 

21 function=FunctionCall(name=block.name or "", arguments=block.input or {}), 

22 ) 

23 

24 

25def _tool_call_to_block(tool_call: ToolCall) -> ClaudeContent: 

26 """Serialize a canonical ``ToolCall`` as a Claude ``tool_use`` block.""" 

27 arguments: Any = tool_call.function.arguments if tool_call.function else {} 

28 if isinstance(arguments, str): 

29 try: 

30 arguments = loads_str(arguments) 

31 except ValueError: 

32 arguments = {} 

33 elif not isinstance(arguments, dict): 

34 arguments = {} 

35 return ClaudeContent( 

36 type="tool_use", 

37 tool_use_id=tool_call.id or f"call_{new_uuid()}", 

38 name=tool_call.function.name if tool_call.function else "", 

39 input=arguments, 

40 )