@@ -29,16 +29,52 @@ def __init__(self, embedder: BaseEmbedder, llm: BaseLLM | None = None):
2929
3030 def create_source (
3131 self ,
32- message : ChatCompletionToolMessageParam ,
32+ message : ChatCompletionToolMessageParam | dict [ str , Any ] ,
3333 info : dict [str , Any ],
3434 ) -> SourceMessage :
35- """Create SourceMessage from tool message."""
35+ """Create SourceMessage from tool message or custom tool format ."""
3636 if not isinstance (message , dict ):
3737 return SourceMessage (type = "chat" , role = "tool" )
3838
39+ # Handle custom tool formats (tool_description, tool_input, tool_output)
40+ msg_type = message .get ("type" , "" )
41+ if msg_type == "tool_description" :
42+ name = message .get ("name" , "" )
43+ description = message .get ("description" , "" )
44+ parameters = message .get ("parameters" , {})
45+ content = f"[tool_description] name={ name } , description={ description } , parameters={ parameters } "
46+ return SourceMessage (
47+ type = "tool_description" ,
48+ content = content ,
49+ original_part = message ,
50+ )
51+ elif msg_type == "tool_input" :
52+ call_id = message .get ("call_id" , "" )
53+ name = message .get ("name" , "" )
54+ argument = message .get ("argument" , {})
55+ content = f"[tool_input] call_id={ call_id } , name={ name } , argument={ argument } "
56+ return SourceMessage (
57+ type = "tool_input" ,
58+ content = content ,
59+ message_id = call_id ,
60+ original_part = message ,
61+ )
62+ elif msg_type == "tool_output" :
63+ call_id = message .get ("call_id" , "" )
64+ name = message .get ("name" , "" )
65+ output = message .get ("output" , {})
66+ content = f"[tool_output] call_id={ call_id } , name={ name } , output={ output } "
67+ return SourceMessage (
68+ type = "tool_output" ,
69+ content = content ,
70+ message_id = call_id ,
71+ original_part = message ,
72+ )
73+
74+ # Handle standard tool message
3975 content = _extract_text_from_content (message .get ("content" , "" ))
4076 return SourceMessage (
41- type = "chat " ,
77+ type = "tool " ,
4278 role = "tool" ,
4379 chat_time = message .get ("chat_time" ),
4480 message_id = message .get ("message_id" ),
@@ -60,10 +96,54 @@ def rebuild_from_source(
6096
6197 def parse_fast (
6298 self ,
63- message : ChatCompletionToolMessageParam ,
99+ message : ChatCompletionToolMessageParam | dict [ str , Any ] ,
64100 info : dict [str , Any ],
65101 ** kwargs ,
66102 ) -> list [TextualMemoryItem ]:
103+ """Parse tool message in fast mode."""
104+ from memos .memories .textual .item import TreeNodeTextualMemoryMetadata
105+
106+ from .base import _derive_key
107+
108+ if not isinstance (message , dict ):
109+ return []
110+
111+ # Handle custom tool formats
112+ msg_type = message .get ("type" , "" )
113+ if msg_type in ("tool_description" , "tool_input" , "tool_output" ):
114+ # Create source
115+ source = self .create_source (message , info )
116+ content = source .content or ""
117+ if not content :
118+ return []
119+
120+ # Extract info fields
121+ info_ = info .copy ()
122+ user_id = info_ .pop ("user_id" , "" )
123+ session_id = info_ .pop ("session_id" , "" )
124+
125+ # Create memory item
126+ memory_item = TextualMemoryItem (
127+ memory = content ,
128+ metadata = TreeNodeTextualMemoryMetadata (
129+ user_id = user_id ,
130+ session_id = session_id ,
131+ memory_type = "LongTermMemory" ,
132+ status = "activated" ,
133+ tags = ["mode:fast" ],
134+ key = _derive_key (content ),
135+ embedding = self .embedder .embed ([content ])[0 ],
136+ usage = [],
137+ sources = [source ],
138+ background = "" ,
139+ confidence = 0.99 ,
140+ type = "fact" ,
141+ info = info_ ,
142+ ),
143+ )
144+ return [memory_item ]
145+
146+ # Handle standard tool message
67147 return super ().parse_fast (message , info , ** kwargs )
68148
69149 def parse_fine (
0 commit comments